#include <linux/init.h>
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
 
static struct dentry *demo_dir;
 
static ssize_t demo_read(struct file *fp, char __user *user_buf, size_t count, loff_t *ppos)
{
    char kbuf[10];
    int wrinten;
 
    printk(KERN_INFO "user_buf: %p, count: %lu, ppos: %lld\n",
        user_buf, count, *ppos);
 
    wrinten = snprintf(kbuf, 10, "%s", "Hello\n");

    //与write不同，cat /sys/kernel/debug/demo只有在read返回0的时候才会停止，否则会一直死循环。即使返回的count等于预期的count参数
    return simple_read_from_buffer(user_buf, count, ppos, kbuf, wrinten);
}
 
static ssize_t demo_write (struct file *fp, const char __user *user_buf, size_t count, loff_t *ppos)
{
    char kbuf[10] = {0};
    int ret;
 
    printk(KERN_INFO "user_buf: %p, count: %lu, ppos: %lld\n",
           user_buf, count, *ppos);
 
    ret = copy_from_user(kbuf, user_buf, count);
    if (ret) {
        pr_err("%s: write error\n", __func__);
        return -EIO;
    }
 
    *ppos += count;
 
    return count;       //若reutrn 0，echo "xxx" > /sys/kernel/debug/demo会死循环
}
 
static const struct file_operations demo_fops = {
    .read = demo_read,
    .write = demo_write,
};
 
static int __init debugfs_demo_init(void)
{
    int ret = 0;
 
    demo_dir = debugfs_create_file("demo", 0444, NULL,
        NULL, &demo_fops);
 
    return ret;
}
 
static void __exit debugfs_demo_exit(void)
{
    if (demo_dir)
        debugfs_remove(demo_dir);
}
 
module_init(debugfs_demo_init);
module_exit(debugfs_demo_exit);
MODULE_LICENSE("GPL");